﻿using System;
using System.Collections.Generic;
using TrueSync;
using UnityEngine;

namespace HEFramework
{
    public static class TrialSystem
    {
        [EntitySystem]
        public class TrialAwakeSystem : AwakeSystem<Trial>
        {
            protected override void Awake(Trial _self)
            {
            }
        }


        [EntitySystem]
        public class TrialUpdateSystem : UpdateSystem<Trial>
        {
            protected override void Update(Trial _self)
            {
                FP deltaTime = Time.deltaTime;
                for (int i = 0; i < _self.Trials.Count; i++)
                {
                    var trial = _self.Trials[i];
                    switch (trial.State)
                    {
                        case eTrialState.Challenging:

                            //已经没有挑战对象了
                            if (!_self.IsChallenging(trial))
                            {
                                trial.State = eTrialState.Cooling;
                            }

                            break;
                        case eTrialState.Cooling:
                            trial.Cooldown -= deltaTime;
                            if (trial.Cooldown <= 0)
                            {
                                trial.Cooldown = 0;
                                //开启下一级挑战
                                _self.NextTrial(trial);
                            }

                            break;
                    }
                }

                using ListObject<TrialChallengeData> temps = ListObject<TrialChallengeData>.Create();

                for (int i = 0; i < _self.TrialChallenges.Count; i++)
                {
                    var challenge = _self.TrialChallenges[i];
                    bool isCompleted = true;
                    for (int j = 0; j < challenge.Targets.Count; j++)
                    {
                        //挑战对象有没有空的
                        if (challenge.Targets[j].Entity != null)
                        {
                            isCompleted = false;
                            break;
                        }
                    }

                    if (isCompleted)
                    {
                        temps.Add(challenge);
                    }
                }

                for (int i = 0; i < temps.Count; i++)
                {
                    var data = temps[i];
                    //获得奖励
                    _self.GetTrialReward(data.ID);
                    _self.TrialChallenges.Remove(data);
                    ObjectGenerater.Instance.Recycle(data);
                }
            }
        }

        [EntitySystem]
        public class TrialDestroySystem : DestroySystem<Trial>
        {
            protected override void Destroy(Trial _self)
            {
                for (int i = 0; i < _self.TrialChallenges.Count; i++)
                {
                    ObjectGenerater.Instance.Recycle(_self.TrialChallenges[i]);
                }

                _self.TrialChallenges.Clear();
            }
        }

        public static void AddTrial(this Trial _self, int _id)
        {
            var dc = _self.GetSceneChild<DataTableComponent>();
            if (dc == null)
            {
                return;
            }

            //添加试炼数据
            _self.Trials.Add(new TrialData()
            {
                ID = _id,
                State = 0,
                Cooldown = Formula.TM(dc.LoadDataTable<DRTrial>().GetData(_id).Cooldown),
            });
        }


        public static void Execute(this Trial _self, int _id)
        {
            var dc = _self.GetSceneChild<DataTableComponent>();
            var factory = _self.GetSceneChild<Factory>();
            if (dc == null || factory == null)
            {
                return;
            }

            var trialData = _self.GetTrialData(_id);
            if (trialData == null || trialData.State != eTrialState.Ready)
            {
                return;
            }

            int teamID = 1;
            int mode = 3;
            var data = dc.LoadDataTable<DRTrial>().GetData(_id);
            TrialChallengeData trialChallengeData = ObjectGenerater.Instance.Fetch<TrialChallengeData>();
            trialChallengeData.ID = _id;

            var table = dc.LoadDataTable<DRGlobalSettings>();
            FP range = Formula.LG(table.GetData((int)eGlobalSetting.Monster_Generate_RAG).Value1);
            FP angle = 0;

            //怪物生成阶段
            switch (data.MonsterGenerateType)
            {
                case (int)eTrialMonsterGenerateType.Random:

                {
                    for (int i = 0; i < data.MonsterIDs.Length; i++)
                    {
                        var e = factory.AddMonster(data.MonsterIDs[i], teamID, factory.GetRandomMonsterGeneratePos());
                        e.GetChild<AlertComponent>().SetType(mode);
                        trialChallengeData.Targets.Add(e);
                    }
                }
                    break;

                case (int)eTrialMonsterGenerateType.Group:

                {
                    TSVector pos = factory.GetRandomMonsterGeneratePos();
                    //初始半径
                    FP initialRadius = 1;
                    //每次循环半径增加的量
                    FP radiusIncrement = 1;
                    // 循环中每次角度增量（以弧度为单位）
                    // 45度的弧度
                    FP angleIncrement = TSMath.Pi / 4;
                    for (int i = 0; i < data.MonsterIDs.Length; i++)
                    {
                        // 计算当前半径
                        FP currentRadius = initialRadius + i * radiusIncrement;
                        // 计算当前角度
                        angle = i * angleIncrement;
                        // 使用极坐标转换为笛卡尔坐标
                        FP x = pos.x + currentRadius * TSMath.Cos(angle);
                        FP y = pos.y + currentRadius * TSMath.Sin(angle);
                        var e = factory.AddMonster(data.MonsterIDs[i], teamID, new TSVector(x, y, 0));
                        e.GetChild<AlertComponent>().SetType(mode);
                        trialChallengeData.Targets.Add(e);
                    }
                }

                    break;

                case (int)eTrialMonsterGenerateType.Horn:

                {
                    for (int i = 0; i < data.MonsterIDs.Length; i++)
                    {
                        angle += i * 90;
                        var e = factory.AddMonster(data.MonsterIDs[i], teamID, _self.AngleToDirection(angle) * range);
                        e.GetChild<AlertComponent>().SetType(mode);
                        trialChallengeData.Targets.Add(e);
                    }
                }


                    break;

                case (int)eTrialMonsterGenerateType.Horizontal:
                {
                    angle = 90;
                    for (int i = 0; i < data.MonsterIDs.Length; i++)
                    {
                        angle += i * 180;
                        var e = factory.AddMonster(data.MonsterIDs[i], teamID, _self.AngleToDirection(angle) * range);
                        e.GetChild<AlertComponent>().SetType(mode);
                        trialChallengeData.Targets.Add(e);
                    }
                }

                    break;

                case (int)eTrialMonsterGenerateType.Vertical:

                {
                    for (int i = 0; i < data.MonsterIDs.Length; i++)
                    {
                        angle += i * 180;
                        var e = factory.AddMonster(data.MonsterIDs[i], teamID, _self.AngleToDirection(angle) * range);
                        e.GetChild<AlertComponent>().SetType(mode);
                        trialChallengeData.Targets.Add(e);
                    }
                }
                    break;
            }

            _self.TrialChallenges.Add(trialChallengeData);

            if (data.WaitChallenging == 1)
            {
                trialData.State = eTrialState.Challenging;
            }
            else
            {
                trialData.State = eTrialState.Cooling;
            }
        }


        private static TrialData GetTrialData(this Trial _self, int _id)
        {
            for (int i = 0; i < _self.Trials.Count; i++)
            {
                if (_self.Trials[i].ID == _id)
                {
                    return _self.Trials[i];
                }
            }

            return null;
        }


        private static void GetTrialReward(this Trial _self, int _id)
        {
            var dc = _self.GetSceneChild<DataTableComponent>();
            var reward = _self.GetSceneChild<Reward>();
            if (dc == null || reward == null)
            {
                return;
            }

            _self.CompletedChallengeIDs.Add(_id);
            var trial = dc.LoadDataTable<DRTrial>().GetData(_id);
            for (int i = 0; i < trial.RewardIDs.Length; i++)
            {
                reward.ChangeTeamReward(trial.RewardIDs[i], trial.RewardValues[i]);
            }
        }


        private static void NextTrial(this Trial _self, TrialData _data)
        {
            var dc = _self.GetSceneChild<DataTableComponent>();
            if (dc == null)
            {
                return;
            }

            var table = dc.LoadDataTable<DRTrial>();
            var data = table.GetData(_data.ID);
            _data.ID = data.Next;
            if (_data.ID == 0)
            {
                //试炼完全结束
                _data.State = eTrialState.End;
            }
            else
            {
                //试炼未结束
                data = table.GetData(_data.ID);
                if (data != null)
                {
                    _data.State = eTrialState.Ready;
                    _data.Cooldown = Formula.TM(data.Cooldown);
                }
                else
                {
                    _data.State = eTrialState.End;
                }
            }
        }

        /// <summary>
        /// 是否在挑战中
        /// </summary>
        /// <param name="_self"></param>
        /// <param name="_data"></param>
        /// <returns></returns>
        private static bool IsChallenging(this Trial _self, TrialData _data)
        {
            for (int i = 0; i < _self.TrialChallenges.Count; i++)
            {
                if (_self.TrialChallenges[i].ID == _data.ID)
                {
                    return true;
                }
            }

            return false;
        }

        private static TSVector AngleToDirection(this Trial _self, FP _angle)
        {
            // 角度转换为弧度
            FP angleInRadians = _angle * FP.Deg2Rad;
            // 计算朝向的向量
            TSVector2 direction = new TSVector2(FP.Cos(angleInRadians), FP.Sin(angleInRadians));
            return new TSVector(direction.x, direction.y, 0);
        }
    }
}